<?php
/**
 * 
 * The module service manages registering and configuring the CMS modules
 *
 * @package    	Digitalus\Core
 * @copyright  	Copyright (c) 2009,  Digitalus Media USA (http://digitalusmedia.net)
 * @license    	New BSD License, library/Dig/License.txt
 * @version 	2.0
 * 
 */
class Dig_Service_Module
{    
    /**
     * Registers the current controller modules with the core.
     *
     * This method fetches the controller directories and then loads each of their
     * config files. It registers these with the CMS core.
     *
     */
    public function registerControllerModules()
    {
        $modules = Zend_Controller_Front::getInstance()->getControllerDirectory();
        $moduleArray = array();
        foreach ($modules as $module => $path) {
            $path = str_replace('controllers', '', $path);
            // load the module's config.ini file
            $config = new Zend_Config_Ini($path . '/' . DIGITALUS_MODULE_CONFIG_FILE);
            $configArray = $config->toArray();
            // add the path to the settings
            $configArray['path'] = $path;
            $moduleArray[$module] = $configArray;
        }
        $preferencesFilePath = APPLICATION_PATH . '/configs/preferences.ini';
        if(file_exists($preferencesFilePath)) {
            $preferences = new Zend_Config_Ini($preferencesFilePath, APPLICATION_ENV);
            $moduleArray = Dig_Service_Array::extendArray($moduleArray, $preferences->toArray());
        }
        Dig_Service_Core::setParam('modules', $moduleArray);
    }
    
    /**
     * tests to see if the module (or an array of modules) exists
     *
     * @param mixed $module The name of the module
     * @param boolean $throwException Whether to throw an exception if the module is not found
     * 
     * @return boolean
     */
    public static function exists($module, $throwException = false)
    {
        if(!is_array($module)) {
            $module = array($module);
        }
        
        $installedModules = self::listAll();
        
        // cycle through the modules, testing that each one exists
        foreach ($module as $mod) {
            if(!array_key_exists($mod, $installedModules)) {
                if($throwException) {
                    throw new Zend_Exception('Required module is not installed: ' . $mod);
                } else {
                    return false;
                }
            }
        }
        return true;
    }
    
    /**
     * returns the modules settings
     * 
     * if module is null then it will search for the key in all of the modules
     * If you specify the key it will return the key, otherwise it returns the whole config array.
     *
     * @param string $module
     * @param string $key
     *
     * @return mixed (either a string or an array)
     */
    public static function settings($module = null, $key = null)
    {
        if(!Dig_Service_Core::hasParam('modules')) {
            self::registerPreferences();
        }
        if($module == null) {
            if($key == null) {
                return false;
            }
            $settings = array();
            foreach (self::listAll() as $moduleName => $moduleConfig) {
                if(isset($moduleConfig[$key])) {
                    $settings[$moduleName] = $moduleConfig[$key];
                }
            }
            if(count($settings) > 0) {
                return $settings;
            } else {
                return false;
            }
        }
        $modules = Dig_Service_Core::getParam('modules');
        $moduleSettings = $modules[$module];
        if(null !== $key) {
            return isset($moduleSettings[$key]) ? $moduleSettings[$key] : false;
        } else {
            return $moduleSettings;
        }
    }
    
    /**
     * Returns an array of all of the installed modules.
     *
     * This is returned as an array where the key is the module name and the value is the module config.
     *
     * @return array
     */
    public static function listAll()
    {
        if(!Dig_Service_Core::hasParam('modules')) {
            self::registerControllerModules();
        }
        return Dig_Service_Core::getParam('modules');
    }

    /**
     * This method fetches the resources from the specified module
     *
     * These resources are the controllers, modules, services, etc. You pass this method
     * the module and type that you need to inspect. It returns them as an array of Zend_Reflection_File objects.
     *
     * @param string $module The name of the module
     * @param string $type The type of resource, eg controllers
     *
     * @return array
     */
    public static function getResources($module, $type) {
        $path = APPLICATION_PATH . '/modules/' . $module . '/' . $type;
        if(! is_dir($path)) {
            return false;
        }
        $resources = array();
        foreach (new DirectoryIterator($path) as $resource) {
            if(!$resource->isFile()) continue;
            $filepath = $resource->getPath() . '/' . $resource->getFilename();
            //Zend_Debug::dump($resource->getPath() . '/' . $resource->getFilename());die();
            require_once $filepath;
            $resources[] = new Zend_Reflection_File($filepath);
        }
        if(count($resources) > 0) {
            return $resources;
        }
    }

    /**
     * This method inspects a controller, model, etc.
     * 
     * @param string $class The name of the class to inspect
     * 
     * @return Zend_Reflection_Class
     */
    public static function inspect($class) {
        $classParts = explode('_', $class);
        if(count($classParts) == 1) {
            $module = 'default';
            // the only items in the default module should be the controllers
            $type = 'controllers';
        } elseif(count($classParts) == 2) {
            $module = $classParts[0];
            $type = 'controllers';
        } else {
            $module = $classParts[0];
            $type = strtolower($classParts[1]) . 's';
        }
        $module = substr_replace($module, strtolower(substr($module, 0, 1)), 0, 1);
        $filename = array_pop($classParts) . '.php';
        require_once APPLICATION_PATH . '/modules/' . $module . '/' . $type . '/' . $filename;
        return new Zend_Reflection_Class($class);
    }

    /**
     * This method builds an array of all of the resources from a module
     * 
     * @param string $module
     * @return array
     */
    public static function getClassIndex($module) {
        $types = array('controllers','models','forms','services','plugins');
        $classes = array();
        foreach ($types as $type) {
            $resources = self::getResources($module, $type);
            if($resources) {
                foreach ($resources as $resource) {
                    $classes[$type][] = $resource->getClass()->getName();
                }
            }
        }
        return $classes;
    }
}

?>